package com.rickpan.controller;

import com.rickpan.dto.common.ApiResponse;
import com.rickpan.storage.health.StorageHealthService;
import com.rickpan.storage.monitor.StorageMetricsService;
import com.rickpan.storage.performance.StoragePerformanceAnalyzer;
import com.rickpan.utils.SecurityUtils;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Meter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 存储监控控制器
 * 提供存储系统监控和性能分析的 API 接口
 */
@RestController
@RequestMapping("/api/storage/monitor")
public class StorageMonitorController {
    
    private static final Logger logger = LoggerFactory.getLogger(StorageMonitorController.class);
    
    @Autowired
    private StorageHealthService healthService;
    
    @Autowired
    private StorageMetricsService metricsService;
    
    @Autowired
    private StoragePerformanceAnalyzer performanceAnalyzer;

    @Autowired
    private MeterRegistry meterRegistry;

    @Autowired
    private com.rickpan.storage.StorageService storageService;

    @Autowired
    private com.rickpan.service.FileManagementService fileManagementService;

    @Autowired
    private com.rickpan.service.FileStorageService fileStorageService;
    
    /**
     * 获取存储健康状态
     * GET /api/storage/monitor/health
     */
    @GetMapping("/health")
    public ApiResponse<Object> getStorageHealth() {
        try {
            StorageHealthService.HealthStatus health = healthService.health();

            Map<String, Object> response = new HashMap<>();
            response.put("status", health.getStatus());
            response.put("details", health.getDetails());

            logger.debug("获取存储健康状态: {}", health.getStatus());

            return ApiResponse.success(response);

        } catch (Exception e) {
            logger.error("获取存储健康状态失败", e);
            return ApiResponse.error("获取存储健康状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取详细健康报告
     * GET /api/storage/monitor/health/detailed
     */
    @GetMapping("/health/detailed")
    public ApiResponse<StorageHealthService.HealthReport> getDetailedHealthReport() {
        try {
            StorageHealthService.HealthReport report = healthService.getDetailedHealthReport();
            
            logger.debug("获取详细健康报告: status={}", report.getStatus());
            
            return ApiResponse.success(report);
            
        } catch (Exception e) {
            logger.error("获取详细健康报告失败", e);
            return ApiResponse.error("获取详细健康报告失败: " + e.getMessage());
        }
    }
    
    /**
     * 强制刷新健康检查
     * POST /api/storage/monitor/health/refresh
     */
    @PostMapping("/health/refresh")
    public ApiResponse<Object> refreshHealthCheck() {
        try {
            StorageHealthService.HealthStatus health = healthService.forceHealthCheck();

            Map<String, Object> response = new HashMap<>();
            response.put("status", health.getStatus());
            response.put("details", health.getDetails());
            response.put("refreshed", true);

            logger.info("强制刷新健康检查完成: {}", health.getStatus());

            return ApiResponse.success(response);

        } catch (Exception e) {
            logger.error("强制刷新健康检查失败", e);
            return ApiResponse.error("强制刷新健康检查失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取存储统计信息
     * GET /api/storage/monitor/stats
     */
    @GetMapping("/stats")
    public ApiResponse<StorageMetricsService.StorageStats> getStorageStats() {
        try {
            StorageMetricsService.StorageStats stats = metricsService.getStorageStats();
            
            logger.debug("获取存储统计信息: totalOps={}, activeOps={}", 
                        stats.getTotalOperations(), stats.getActiveOperations());
            
            return ApiResponse.success(stats);
            
        } catch (Exception e) {
            logger.error("获取存储统计信息失败", e);
            return ApiResponse.error("获取存储统计信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取性能分析报告
     * GET /api/storage/monitor/performance
     */
    @GetMapping("/performance")
    public ApiResponse<StoragePerformanceAnalyzer.PerformanceReport> getPerformanceReport() {
        try {
            StoragePerformanceAnalyzer.PerformanceReport report = performanceAnalyzer.generatePerformanceReport();
            
            logger.info("生成性能分析报告: {} 个问题, {} 条建议", 
                       report.getIssues().size(), report.getRecommendations().size());
            
            return ApiResponse.success(report);
            
        } catch (Exception e) {
            logger.error("获取性能分析报告失败", e);
            return ApiResponse.error("获取性能分析报告失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取所有监控指标
     * GET /api/storage/monitor/metrics
     */
    @GetMapping("/metrics")
    public ApiResponse<Object> getAllMetrics() {
        try {
            Map<String, Object> metrics = new HashMap<>();
            
            // 获取存储相关的指标
            List<Meter> storageMeters = meterRegistry.getMeters().stream()
                .filter(meter -> meter.getId().getName().startsWith("storage."))
                .collect(Collectors.toList());
            
            Map<String, Object> storageMetrics = new HashMap<>();
            for (Meter meter : storageMeters) {
                String name = meter.getId().getName();
                Map<String, String> tags = meter.getId().getTags().stream()
                    .collect(Collectors.toMap(
                        tag -> tag.getKey(),
                        tag -> tag.getValue()
                    ));
                
                Object value = "N/A";
                String meterType = meter.getClass().getSimpleName();

                if (meter instanceof io.micrometer.core.instrument.Counter) {
                    value = ((io.micrometer.core.instrument.Counter) meter).count();
                    meterType = "Counter";
                } else if (meter instanceof io.micrometer.core.instrument.Timer) {
                    io.micrometer.core.instrument.Timer timer = (io.micrometer.core.instrument.Timer) meter;
                    value = Map.of(
                        "count", timer.count(),
                        "totalTime", timer.totalTime(java.util.concurrent.TimeUnit.MILLISECONDS),
                        "mean", timer.mean(java.util.concurrent.TimeUnit.MILLISECONDS),
                        "max", timer.max(java.util.concurrent.TimeUnit.MILLISECONDS)
                    );
                    meterType = "Timer";
                } else if (meter instanceof io.micrometer.core.instrument.Gauge) {
                    value = ((io.micrometer.core.instrument.Gauge) meter).value();
                    meterType = "Gauge";
                } else if (meter instanceof io.micrometer.core.instrument.DistributionSummary) {
                    io.micrometer.core.instrument.DistributionSummary summary =
                        (io.micrometer.core.instrument.DistributionSummary) meter;
                    value = Map.of(
                        "count", summary.count(),
                        "totalAmount", summary.totalAmount(),
                        "mean", summary.mean(),
                        "max", summary.max()
                    );
                    meterType = "DistributionSummary";
                }

                String key = name + (tags.isEmpty() ? "" : "_" + tags.toString());
                storageMetrics.put(key, Map.of(
                    "name", name,
                    "type", meterType,
                    "tags", tags,
                    "value", value
                ));
            }
            
            metrics.put("storage", storageMetrics);
            metrics.put("timestamp", System.currentTimeMillis());
            metrics.put("totalMeters", storageMeters.size());
            
            logger.debug("获取监控指标: {} 个存储相关指标", storageMeters.size());
            
            return ApiResponse.success(metrics);
            
        } catch (Exception e) {
            logger.error("获取监控指标失败", e);
            return ApiResponse.error("获取监控指标失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取特定指标
     * GET /api/storage/monitor/metrics/{metricName}
     */
    @GetMapping("/metrics/{metricName}")
    public ApiResponse<Object> getSpecificMetric(@PathVariable String metricName) {
        try {
            List<Meter> meters = meterRegistry.getMeters().stream()
                .filter(meter -> meter.getId().getName().equals(metricName))
                .collect(Collectors.toList());
            
            if (meters.isEmpty()) {
                return ApiResponse.error("指标不存在: " + metricName);
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("metricName", metricName);
            result.put("values", meters.stream().map(meter -> {
                Map<String, Object> meterInfo = new HashMap<>();
                meterInfo.put("tags", meter.getId().getTags().stream()
                    .collect(Collectors.toMap(
                        tag -> tag.getKey(),
                        tag -> tag.getValue()
                    )));
                
                if (meter instanceof io.micrometer.core.instrument.Counter) {
                    meterInfo.put("value", ((io.micrometer.core.instrument.Counter) meter).count());
                } else if (meter instanceof io.micrometer.core.instrument.Timer) {
                    io.micrometer.core.instrument.Timer timer = (io.micrometer.core.instrument.Timer) meter;
                    meterInfo.put("value", Map.of(
                        "count", timer.count(),
                        "mean", timer.mean(java.util.concurrent.TimeUnit.MILLISECONDS)
                    ));
                } else if (meter instanceof io.micrometer.core.instrument.Gauge) {
                    meterInfo.put("value", ((io.micrometer.core.instrument.Gauge) meter).value());
                } else {
                    meterInfo.put("value", "N/A");
                }
                
                return meterInfo;
            }).collect(Collectors.toList()));
            
            logger.debug("获取特定指标: {} ({} 个值)", metricName, meters.size());
            
            return ApiResponse.success(result);
            
        } catch (Exception e) {
            logger.error("获取特定指标失败: {}", metricName, e);
            return ApiResponse.error("获取特定指标失败: " + e.getMessage());
        }
    }
    
    /**
     * 调试文件路径和存储位置
     * GET /api/storage/monitor/debug/file/{fileId}
     */
    @GetMapping("/debug/file/{fileId}")
    public ApiResponse<Object> debugFile(@PathVariable Long fileId) {
        try {
            // 查询文件信息 - 使用当前认证用户
            Long currentUserId = SecurityUtils.getCurrentUserId();
            var fileInfo = fileManagementService.getFileDetail(currentUserId, fileId);

            Map<String, Object> debug = new HashMap<>();
            debug.put("fileId", fileId);
            debug.put("fileName", fileInfo.getOriginalName());
            debug.put("filePath", fileInfo.getFilePath());
            debug.put("currentStorageType", storageService.getStorageType());

            // 检查本地文件是否存在
            try {
                java.nio.file.Path localPath = fileStorageService.getAbsolutePath(fileInfo.getFilePath());
                boolean localExists = java.nio.file.Files.exists(localPath);
                debug.put("localPath", localPath.toString());
                debug.put("existsLocally", localExists);
                if (localExists) {
                    debug.put("localFileSize", java.nio.file.Files.size(localPath));
                }
            } catch (Exception e) {
                debug.put("localCheckError", e.getMessage());
                debug.put("existsLocally", false);
            }

            // 检查 MinIO 文件（如果当前是 MinIO 存储）
            if ("minio".equals(storageService.getStorageType())) {
                try {
                    // 尝试生成 URL 来间接检查文件是否存在
                    String downloadUrl = storageService.generateDownloadUrl(fileInfo.getFilePath(), java.time.Duration.ofMinutes(5));
                    debug.put("minioDownloadUrl", downloadUrl);
                    debug.put("minioUrlGenerated", true);
                } catch (Exception e) {
                    debug.put("minioError", e.getMessage());
                    debug.put("minioUrlGenerated", false);
                }
            }

            return ApiResponse.success(debug);

        } catch (Exception e) {
            logger.error("调试文件失败: fileId={}", fileId, e);
            return ApiResponse.error("调试失败: " + e.getMessage());
        }
    }

    /**
     * 调试 MinIO 连接和文件状态
     * GET /api/storage/monitor/debug/{filePath}
     */
    @GetMapping("/debug/{filePath}")
    public ApiResponse<Object> debugMinIOFile(@PathVariable String filePath) {
        try {
            Map<String, Object> debug = new HashMap<>();

            // 检查存储类型
            debug.put("storageType", "minio");

            // 检查健康状态
            StorageHealthService.HealthStatus health = healthService.health();
            debug.put("healthStatus", health.getStatus());
            debug.put("healthDetails", health.getDetails());

            // 尝试生成 URL
            try {
                String downloadUrl = storageService.generateDownloadUrl(filePath, java.time.Duration.ofMinutes(5));
                debug.put("downloadUrl", downloadUrl);
                debug.put("urlGenerated", true);
            } catch (Exception e) {
                debug.put("urlError", e.getMessage());
                debug.put("urlGenerated", false);
            }

            debug.put("timestamp", System.currentTimeMillis());

            return ApiResponse.success(debug);

        } catch (Exception e) {
            logger.error("调试 MinIO 文件失败: {}", filePath, e);
            return ApiResponse.error("调试失败: " + e.getMessage());
        }
    }

    /**
     * 获取监控概览
     * GET /api/storage/monitor/overview
     */
    @GetMapping("/overview")
    public ApiResponse<Object> getMonitoringOverview() {
        try {
            Map<String, Object> overview = new HashMap<>();
            
            // 健康状态
            StorageHealthService.HealthStatus health = healthService.health();
            overview.put("health", Map.of(
                "status", health.getStatus(),
                "healthy", health.getStatus().equals("UP")
            ));
            
            // 基本统计
            StorageMetricsService.StorageStats stats = metricsService.getStorageStats();
            overview.put("stats", stats);
            
            // 性能概览
            StoragePerformanceAnalyzer.PerformanceReport perfReport = performanceAnalyzer.generatePerformanceReport();
            overview.put("performance", Map.of(
                "issueCount", perfReport.getIssues().size(),
                "recommendationCount", perfReport.getRecommendations().size(),
                "criticalIssues", perfReport.getIssues().stream()
                    .filter(issue -> issue.getSeverity() == StoragePerformanceAnalyzer.PerformanceIssue.Severity.CRITICAL)
                    .count()
            ));
            
            overview.put("timestamp", System.currentTimeMillis());
            
            logger.debug("获取监控概览: health={}, totalOps={}, issues={}",
                        health.getStatus(), stats.getTotalOperations(), perfReport.getIssues().size());
            
            return ApiResponse.success(overview);
            
        } catch (Exception e) {
            logger.error("获取监控概览失败", e);
            return ApiResponse.error("获取监控概览失败: " + e.getMessage());
        }
    }
}
